using System;
using System.Collections;
using System.Collections.Generic;
using System.Html;
using System.Runtime.CompilerServices;
using Awaiter;
using MetaPages.Classes;
using MetaTests.Classes;
using Nsb;
using Nsb.Classes;
using Yoshi.Classes;
using YoshiBase.Classes;
using jQueryApi;

namespace MetaPages.Clusters
{
    [IgnoreNamespace]
    public class MetaCluster : Actor
    {
        private const int SlideSpeed = 100;
        public const string TestUserId = "TestUserId";
        private static MetaCluster _instance;
        private static bool _usersSimulated = TestAuthenticate();
        public static jQueryObject TestTeller;
        public static jQueryObject _userSelect;

        public static readonly Dictionary TestUsers = new Dictionary(
            "TestUser1", "TestUser1",
            "TestUser2", "TestUser2",
            "TestUser3", "TestUser3",
            "Nathan", "1305946510",
            "Natalie", "793889201",
            "Shallon", "746605760",
            "Kickin", "100002776766039"
            );

        private string _barMargin;
        private string _bodyMargin;

        private jQueryObject _testBtn;
        private TestSuite _testSuite;
        private bool _userBoxUpdate;

        private MetaCluster()
        {
            new Await()
                .LoadCss("Scripts/Css/MetaCluster.css")
                .AddDx(
                    delegate
                    {
                        Element = jQuery.FromHtml("<div class='MetaCluster'/>").AppendTo(Document.Body).Hide();

                        _bodyMargin = jQuery.FromObject(Document.Body).GetCSS("margin-top");
                        _barMargin = (Element.GetHeight() + Number.ParseInt(_bodyMargin)) + "px";

                        jQuery.FromHtml("<button/>")
                            .AppendTo(Element)
                            .Html("css")
                            .Click(delegate(jQueryEvent e) { CssInfo.Ev(e, jQuery.FromElement(e.Target)); })
                            ;

                        jQuery.FromHtml("<button class='RefreshBtn'/>")
                            .AppendTo(Element)
                            .Html("refresh")
                            .Click(delegate
                                   {
                                       if (!String.IsNullOrEmpty(Window.Location.Search))
                                       {
                                           Window.Location.Href = Window.Location.Href.Split("?")[0];
                                       }
                                       else
                                           Window.Location.Reload(true);
                                   })
                            ;

                        _userSelect = jQuery.FromHtml("<select class='UserSelect'/>")
                            .AppendTo(Element)
                            ;
                        jQuery.FromHtml("<option/>").AppendTo(_userSelect).Attribute("value", "live").Html("live user");

                        foreach (KeyValuePair<string, object> p in TestUsers)
                        {
                            if (p.Value is string)
                                jQuery.FromHtml("<option/>").AppendTo(_userSelect).Attribute("value", (string)p.Value).Html(p.Key);
                        }

                        Await awx = new Await()
                            .WaitDx(delegate { return Master.FbUser != null && Script.IsValue(Master.FbUser.id); }, 2000);
                        if (Script.IsValue(Storage.GetLocal(TestUserId)))
                            awx.AddDx(delegate { _userSelect.Value(Master.Profile.MyId); });
                        else
                            awx.AddDx(delegate { _userSelect.Value("live"); });
                        awx
                            .AddDx(delegate { _userSelect.Change(delegate { ChangeUser(_userSelect.GetValue()); }); })
                            .AddDx(
                                delegate
                                {
                                    new DropMenu(
                                        _userSelect,
                                        new Dictionary(
                                            "Master.alivenessCheck()", "Aliveness Check"
                                            ),
                                        delegate(jQueryEvent e, string item) { Script.Eval(item); }
                                        );
                                })
                            .Commit();

                        TestTeller = jQuery.FromHtml("<div class='TestTeller'/>")
                            .AppendTo(Element)
                            ;

                        _testBtn = jQuery.FromHtml("<button class='RunTestsBtn'/>")
                            .AppendTo(Element)
                            .Html("Run Tests")
                            .Click(
                                delegate { TestSuite.RunMasterSuite(); }
                            )
                            ;

                        jQueryObject goPage = jQuery.FromHtml("<select class='GoPage'/>")
                            .AppendTo(Element)
                            // ReSharper disable PossibleNullReferenceException
                            .Change(delegate { Master.GoPage(jQuery.Select(".MetaCluster .GoPage").GetValue()); })
                            // ReSharper restore PossibleNullReferenceException
                            ;

                        foreach (KeyValuePair<string, string> p in ThemeBase.OldPages)
                        {
                            jQuery.FromHtml("<option/>").Attribute("value", p.Key).Html(p.Value).AppendTo(goPage);
                        }

                        Refresh();

                        SlideDown();
                    })
                .Commit();
        }

        public void Refresh()
        {
            if (_testBtn != null)
                new Await()
                    .LoadScript("Scripts/MetaTests.debug.js")
                    .AddDx(
                        delegate
                        {
                            Test.TestUserId = TestUserId;
                            TestSuite.Teller = TestTeller;
                            TestSuite.Tell(null);
                            _testSuite = TestSuite.GetTestSuiteByPage(ThemeBase.CurrentPageClass);
                            Dictionary list = _testSuite != null ? _testSuite.TestList() : new Dictionary();
                            //if (list.Count == 0)
                            //    _testBtn.Attribute("disabled", "disabled");
                            //else
                            //    _testBtn.RemoveAttr("disabled");
                            new TestListMenu(
                                _testBtn,
                                list,
                                delegate(jQueryEvent e, string item) { _testSuite.Run(item); }
                                );

                            UpdateUserBox((string)Storage.GetLocal(TestUserId));

                        })
                    .Commit();
        }

        private void UpdateUserBox(string id)
        {
            if (Master.FbUser == null)
            {
                Window.SetTimeout(delegate { UpdateUserBox(id); }, 13);
                return;
            }
            if (id != null)
            {
                new Await()
                    .AddDx(delegate { _userBoxUpdate = true; })
                    .AddDx(delegate { _userSelect.Value(id); })
                    .AddDx(delegate { _userBoxUpdate = false; })
                    .Commit();
            }
        }

        public static void StaticRefresh()
        {
            if (_instance != null)
                _instance.Refresh();
        }

        public static void Ev(jQueryEvent e)
        {
            if (_instance == null)
                _instance = new MetaCluster();
            else
            {
                if (_instance.Element.Is(":visible"))
                    _instance.SlideUp();
                else
                    _instance.SlideDown();
            }
            _instance.Refresh();
        }

        internal void SlideDown()
        {
            Storage.SetLocal("MetaBar", true);
            jQuery.FromObject(Document.Body).Animate(new Dictionary("padding-top", _barMargin), new Dictionary("duration", SlideSpeed));
            SlideDownAw(Await.AsyncAw, SlideSpeed);
        }

        internal void SlideUp()
        {
            Storage.SetLocal("MetaBar", false);
            jQuery.FromObject(Document.Body).Animate(new Dictionary("padding-top", _bodyMargin), new Dictionary("duration", SlideSpeed));
            SlideUpAw(Await.AsyncAw, SlideSpeed);
        }

        public void Destroy()
        {
            _instance = null;
            SlideUp();
            Storage.RemoveLocal("MetaBar");
            Element.Remove();
        }

        private static bool TestAuthenticate()
        {
            _usersSimulated = !_usersSimulated; // Keep ReSharper happy
            if (Script.IsValue(Storage.GetLocal(TestUserId)))
            {
                Script.Literal("FbDataStore.prototype.authenticateAw = MetaCluster.testAuthAw");
                Master.Testing = true;
            }
            return true;
        }

        public static void TestAuthAw(Await awp)
        {
            string id = Script.Value((string)Storage.GetLocal(TestUserId), (string)TestUsers["Nathan"]);
            new Await()
                .AddAw(ProfileData.GetUserByIdAw, id)
                .AddDx(
                    delegate(Await aw)
                    {
                        YoshiUser ysr = (YoshiUser)aw["result"];
                        if (ysr != null)
                            Master.Profile.My = ysr;
                    }
                )
                .Commit(awp);
        }

        public void ChangeUser(string id)
        {
            if (_userBoxUpdate)
                return;
            if (id == "live")
            {
                Storage.RemoveLocal(TestUserId);
                Window.Location.Reload(true);
            }
            else
            {
                Script.Literal("FbDataStore.prototype.authenticateAw = MetaCluster.testAuthAw");
                Master.Testing = true;
                Storage.SetLocal(TestUserId, id);
                Master.GoPage(ThemeBase.CurrentPageClass);
                UpdateUserBox(id);
            }
        }
    }
}